<?php
/**
 * Created by PhpStorm.
 * User: Administrator
 * Date: 2019/8/20 0020
 * Time: 14:02
 */

namespace common\models\WxPublic;


use common\components\DataHelper;
use common\components\Services\Wechat;
use common\models\PlugsRunTotal\PlugsRunTotal;
use common\models\WxDisabledArea\WxDisabledArea;
use common\models\WxExposureNumber\WxExposureNumber;
use common\models\WxFollowLog\WxFollowLog;
use yii\db\ActiveQuery;
use yii\db\Expression;

class WxPublic extends WxPublicBase
{
    public $exposure_rate_sum;

    public static function createSearchCondition(ActiveQuery $query, $params)
    {
        if ( @$params["status"] ) {
            $query->andWhere([
                "status" => @$params["status"]
            ]);
        }

        if ( @$params["name"] ) {
            $query->andWhere([
                "like",
                "name",
                $params["name"]
            ]);
        }
    }


    public function rules()
    {
        return array_merge([
            ['exposure_rate', 'compare', 'compareValue' => 0, 'operator' => '>', "message" => "曝光率必须大于0"],
            ['exposure_rate', 'compare', 'compareValue' => 100, 'operator' => '<=', "message" => "曝光率必须小于等于100"],
            ["status", "filter", "filter" => "intval"]
        ], parent::rules()); // TODO: Change the autogenerated stub
    }

    public static function setRow(array $data, $id = 0)
    {
        if ( $id ) {
            $query = self::findOne($id);
            if ( !$query ) {
                self::error("未知的数据");
                return false;
            }
        } else {
            $query = new self();
            $query->created_time = DataHelper::date();
            $query->updated_time = $query->created_time;
        }
        $query->attributes = $data;
        if ( DataHelper::isEmpty($data["disabled_area"]) ) {
            $query->is_all_area = self::IS_YES;
        } else {
            $data["disabled_area"] = explode(",", $data["disabled_area"]);
            foreach ( $data["disabled_area"] as $key => &$item ) {
                $city = PlugsRunTotal::formatAddress($item);
                $item = @$city[1];
                if ( !$item ) {
                    unset($data["disabled_area"][$key]);
                }
            }
            $query->is_all_area = $data["disabled_area"] ? self::IS_NO : self::IS_YES;
        }
        if ( !$query->save() ) {
            self::error($query->getFirstErrorToStr());
            return false;
        }
        //设置地区
        if ( !DataHelper::isEmpty($data["disabled_area"]) ) {
            $wxDisabledArea = new WxDisabledArea();
            $ret = $wxDisabledArea->setLinkRows("wx_public_id", $query->id, "city", $data["disabled_area"]);
            if ( !$ret ) {
                self::error("数据已保存，但地区保存失败：" . $wxDisabledArea->getFirstErrorToStr());
                return false;
            }
        } else {
            WxDisabledArea::deleteAll([
                "wx_public_id" => $query->id
            ]);
        }
        return true;
    }

    public function afterSave($insert, $changedAttributes)
    {
        //如果是新增数据 或者修改状态 或者达到终止关注数
        if ( $insert || isset($changedAttributes["exposure_rate"]) || isset($changedAttributes["status"]) ) {
            self::updateExposureNum();
            //或者说调整了 终止关注数
        } elseif (  isset($changedAttributes["total_follow"])  && $this->total_follow >= $this->stop_follow_num ) {
            self::updateExposureNum("id<>" . $this->id);
        } elseif ( isset($changedAttributes["stop_follow_num"]) && $this->total_follow >= $this->stop_follow_num ) {
            self::updateExposureNum("id<>" . $this->id);
        }

        //设置菜单
        if ( @$changedAttributes["menu"] ) {
            $app = Wechat::NewWechat($this->app_id, $this->secret)->app;
            $menu = json_decode($this->menu, true);
            $menu = self::formatMenu($menu);
            $app->menu->create($menu);
        }
        parent::afterSave($insert, $changedAttributes); // TODO: Change the autogenerated stub
    }

    public static function formatMenu(array $menu)
    {
        if ( isset($menu["button"]) ) {
            return $menu["button"];
        }
        return $menu;
    }

    public static function updateExposureNum($condition = "", $params = [])
    {
        $ret = self::find()->select(["sum(exposure_rate) as exposure_rate"])->where(self::getExposureNumCondition())->asArray()->one();
        $ret = intval(@$ret["exposure_rate"]);
        return self::updateAll([
            "exposure_num" => new Expression("round((exposure_rate/$ret) * 10)")
        ], $condition, $params);
    }

    public static function getExposureNumCondition()
    {
        return [
            "and",[
                "=", "status", self::STATUS_YES
            ],[
                "<", "total_follow", new Expression("`stop_follow_num`")
            ]
        ];
    }

    public function getArea()
    {
        return $this->hasMany(WxDisabledArea::class, [
            "wx_public_id" => "id"
        ]);
    }

    public function getENumber()
    {
        return $this->hasOne(WxExposureNumber::class, [
            "wx_public_id" => "id",
        ])->select(["wx_public_id", "sum(number) as number"]);
    }

    public function getFNumber()
    {
        return $this->hasOne(WxFollowLog::class, [
            "wx_public_id" => "id",
        ])->select(["wx_public_id", "count(*) as number"]);
    }

    /**
     * 增加中曝光量
     * @param int $num
     * @return false|int
     */
    public function addTotalExposure($num = 1)
    {
        $num = intval($num);
        if ( !$num ) {
            $this->addError("num", "无效的NUM");
            return false;
        }
        $date = date("Y-m-d");
        $transaction = self::getDb()->beginTransaction();

        //增加今日曝光量
        $wxExposureNumber = WxExposureNumber::findOne([
            "wx_public_id" => $this->id,
            "created_date" => $date
        ]);
        if ( !$wxExposureNumber ) {
            $wxExposureNumber = new WxExposureNumber();
            $wxExposureNumber->wx_public_id = $this->id;
            $wxExposureNumber->created_date = $date;
            $wxExposureNumber->number = 0;
            if ( !$wxExposureNumber->insert(0) ) {
                $transaction->rollBack();
                $this->addError("今日曝光量写入失败");
                return false;
            }
        }
        $wxExposureNumber->lockForUpdate();
        $wxExposureNumber->number += $num;
        if ( !$wxExposureNumber->update(0) ) {
            $transaction->rollBack();
            $this->addError("今日曝光量写入失败");
            return false;
        }

        $this->lockForUpdate();
        $this->total_exposure += $num;
        $ret = $this->update(0);
        if ( $ret ) {
            $transaction->commit();
            return true;
        }
        $transaction->rollBack();
        return false;/* 需要执行beforeSave 所以不能直接update
        return self::updateAllCounters([
            "total_exposure" => $num
        ], [
            "id" => $this->id
        ]);*/
    }

    /**
     * 增加总关注量
     * @param int $openId
     * @return false|int
     */
    public function addTotalFollow($openId)
    {
        if ( !$openId ) {
            $this->addError("num", "无效的Openid");
            return false;
        }

        //查看对应openid是否已经关注过
        $wxFollowLog = WxFollowLog::findOne([
            "wechat_open_id" => $openId
        ]);
        if ( $wxFollowLog ) {
            return null;
        }
        $transaction = self::getDb()->beginTransaction();

        $wxFollowLog = new WxFollowLog();
        $wxFollowLog->wechat_open_id = $openId;
        $wxFollowLog->wx_public_id = $this->id;
        $wxFollowLog->created_date = date("Y-m-d");
        $wxFollowLog->created_ym = date("Y-m");
        if ( !$wxFollowLog->insert(0) ) {
            $transaction->rollBack();
            self::error("openid 写入失败");
            return false;
        }

        $this->lockForUpdate();
        $this->total_follow += 1;
        $ret = $this->update(0);
        if ( $ret ) {
            $transaction->commit();
            return true;
        }
        $transaction->rollBack();
        return false;/*
        return self::updateAllCounters([
            "total_follow" => $num
        ], [
            "id" => $this->id
        ]);*/
    }
}